﻿var HeadTS;
(function (HeadTS) {
    (function (DocumentResourceType) {
        /// <summary>
        /// Types of document resources.
        /// </summary>
        /// <field name="script">A script resource.</field>
        DocumentResourceType[DocumentResourceType["script"] = 0] = "script";

        /// <field name="style">A style resource.</field>
        DocumentResourceType[DocumentResourceType["style"] = 1] = "style";
    })(HeadTS.DocumentResourceType || (HeadTS.DocumentResourceType = {}));
    var DocumentResourceType = HeadTS.DocumentResourceType;
})(HeadTS || (HeadTS = {}));
/// <reference path="DocumentResourceType.ts" />
var HeadTS;
(function (HeadTS) {
    var DocumentResource = (function () {
        /// <summary>
        /// A resource that can be added to a document.
        /// </summary>
        function DocumentResource(type, sources, name, namedDependencies, test) {
            if (typeof name === "undefined") { name = null; }
            if (typeof namedDependencies === "undefined") { namedDependencies = []; }
            if (typeof test === "undefined") { test = function () {
                return true;
            }; }
            this.type = type;
            this.sources = sources;
            this.name = name;
            this.namedDependencies = namedDependencies;
            this.test = test;
            // If we have no sources defined, throw an exception since we can't do anything without at least one.
            if ((sources === null) || (sources.length === 0)) {
                throw "At least one source is required.";
            }

            // If no name was provided, generate one from the first entry.
            if ((name === null) || (name.length === 0)) {
                this.name = ResourceUtilities.createResourceNameFromLocation(sources[0]);
            }
        }
        DocumentResource.createForScript = function (sources, name, namedDependencies, test) {
            return new DocumentResource(0 /* script */, sources, name, namedDependencies, test);
        };

        DocumentResource.createForStyle = function (sources, name, namedDependencies, test) {
            return new DocumentResource(1 /* style */, sources, name, namedDependencies, test);
        };
        return DocumentResource;
    })();
    HeadTS.DocumentResource = DocumentResource;

    var ResourceUtilities = (function () {
        function ResourceUtilities() {
        }
        ResourceUtilities.createResourceNameFromLocation = function (location) {
            var pathComponents = location.split('/');
            return pathComponents[pathComponents.length - 1];
        };
        return ResourceUtilities;
    })();
})(HeadTS || (HeadTS = {}));
/*
Promises, Promises...
A light-weight implementation of the Promise/A+ specification (http://promises-aplus.github.io/promises-spec/) and an underlying deferred-execution (i.e. future) provider and useful extensions.
This library is meant to provide core functionality required to leverage Promises / futures within larger libraries via bundling or otherwise inclusion within larger files.
Author:     Mike McMahon
Created:    September 5, 2013
Version:    3.0.2
Updated:    March 16, 2014
Project homepage: http://promises.codeplex.com
*/
var Promises;
(function (Promises) {
    "use strict";

    

    

    //#endregion
    //#region Utility Methods
    var isFunction = function (itemToCheck) {
        /// <summary>Determines whether an item represents a function.</summary>
        /// <param name="itemToCheck" type="any">An item to examine.</param>
        /// <returns type="Boolean">true if the item is a function; otherwise, false.</returns>
        var f = function () {
        };
        return itemToCheck && ((typeof itemToCheck) === (typeof f));
    };

    var Scheduler = (function () {
        function Scheduler() {
        }
        Scheduler.scheduleExecution = (function () {
            // Determine what's available (safely) by testing whether "setImmediate" is actually available.
            var setImmediateExists = false;
            try  {
                setImmediateExists = isFunction(setImmediate);
            } catch (doesntExist) {
            }

            // If setImmediate is available, use that.
            // Otherwise, use setTimeout as our fallback.
            // In either case, we ensure that our execution context is the global scope (i.e. null).
            if (setImmediateExists) {
                return function (f) {
                    setImmediate.call(null, f);
                };
            } else {
                // We have to check for the presence of the "call" method since old IE doesn't provide it for setTimeout.
                if (setTimeout.call) {
                    return function (f) {
                        setTimeout.call(null, f, 0);
                    };
                } else {
                    return function (f) {
                        setTimeout(f, 0);
                    };
                }
            }
        })();
        return Scheduler;
    })();
    Promises.Scheduler = Scheduler;
})(Promises || (Promises = {}));
/*
Promises, Promises...
A light-weight implementation of the Promise/A+ specification (http://promises-aplus.github.io/promises-spec/) and an underlying deferred-execution (i.e. future) provider and useful extensions.
This library is meant to provide core functionality required to leverage Promises / futures within larger libraries via bundling or otherwise inclusion within larger files.
Author:     Mike McMahon
Created:    September 5, 2013
Version:    3.0.2
Updated:    March 16, 2014
Project homepage: http://promises.codeplex.com
*/
/// <reference path="Common interfaces.ts" />
/// <reference path="Scheduler.ts" />
var Promises;
(function (Promises) {
    "use strict";

    

    //#endregion
    //#region Enumerations
    /// <field name="DeferredState" static="true" type="Number">Possible states of a Deferred.</field>
    (function (DeferredState) {
        /// <field name="Pending" static="true">Awaiting completion (i.e. neither resolved nor rejected).</field>
        DeferredState[DeferredState["Pending"] = 0] = "Pending";

        /// <field name="Fulfilled" static="true">Completed successfully (i.e. success).</field>
        DeferredState[DeferredState["Fulfilled"] = 1] = "Fulfilled";

        /// <field name="Rejected" static="true">Completed erroneously (i.e. failure).</field>
        DeferredState[DeferredState["Rejected"] = 2] = "Rejected";
    })(Promises.DeferredState || (Promises.DeferredState = {}));
    var DeferredState = Promises.DeferredState;

    //#endregion
    //#region Utility Methods
    var isFunction = function (itemToCheck) {
        /// <summary>Determines whether an item represents a function.</summary>
        /// <param name="itemToCheck" type="any">An item to examine.</param>
        /// <returns type="Boolean">true if the item is a function; otherwise, false.</returns>
        var f = function () {
        };
        return itemToCheck && ((typeof itemToCheck) === (typeof f));
    }, isObject = function (itemToCheck) {
        /// <summary>Determines whether an item represents an Object.</summary>
        /// <param name="itemToCheck" type="any">An item to examine.</param>
        /// <returns type="Boolean">true if the item is an Object; otherwise, false.</returns>
        return itemToCheck && ((typeof itemToCheck) === (typeof {}));
    };

    //#endregion
    //#region The Promise Resolution Procedure
    // This is the implementation of The Promise Resolution Procedure of the Promises/A+ Specification (2.3)
    var resolvePromise = function (promise, result) {
        // Take action depending upon the result returned (if any).
        // The specification provides several cases for processing.
        if ((result !== undefined) && (result !== null)) {
            // We have a result of some sort, so take action accordingly.
            if (result instanceof Promises.Promise) {
                // The value is our kind of promise, so we assume its state, unless it's the same instance.
                if (promise.then === result.then) {
                    // The value returned by the callback is the continuation promise (which is all we actually would return from this method), so reject the continuation providing a TypeError as a reason, per the specification.
                    // We used a reference test of the "then" method to make this determination quickly.
                    promise.reject(new TypeError());
                } else {
                    // We can take this shortcut here since we know it's implemented correctly.
                    // We do take the precaution of fulfilling the promise with the result value via The Promise Resolution Procedure, a choice that is only implied by the specification, but required to pass the tests.
                    result.then(function (r) {
                        return resolvePromise(promise, r);
                    }, promise.reject);
                    return;
                }
            } else if (isObject(result) || isFunction(result)) {
                // Attempt to import the "thenable."
                var wrapper = Promises.Promise.fromThenable(result);

                // If the import succeeded, we assume the state of the wrapper promise.
                // Otherwise, this wasn't a viable "thenable" and we just treat it like an object.
                if (wrapper != null) {
                    wrapper.then(function (r) {
                        return resolvePromise(promise, r);
                    }, promise.reject);
                    return;
                }
            }
        }

        // As a final step, we resolve the promise with the result.
        // All the previous logic applies special processing conditionally, returning when appropriate.
        // This handles a large number of cases, acting as the catch-all when we don't handle the value specially.
        promise.fulfill(result);
    };

    //#endregion
    //#region The private InnerDeferred type
    var InnerDeferred = (function () {
        function InnerDeferred() {
            /// <summary>
            /// Initializes a new Deferred that can be fulfilled nor rejected.
            /// </summary>
            // Initialize the member fields.
            this.state = 0 /* Pending */;
            this.fulfilledContinuations = [];
            this.rejectedContinuations = [];
        }
        InnerDeferred.prototype.fulfill = function (result) {
            /// <summary>Resolves this Deferred as having been fulfilled, passing an optional result value.</summary>
            /// <param name="result" type="Object">Any data to be passed as the result of this Deferred to its fulfillment handlers.</param>
            if (this.state === 0 /* Pending */) {
                this.state = 1 /* Fulfilled */;
                this.resultData = result;

                while (this.fulfilledContinuations.length > 0) {
                    this.fulfilledContinuations.shift()(this.resultData);
                }

                // Clear out the rejection continuations.
                this.rejectedContinuations = null;
            }
        };

        InnerDeferred.prototype.reject = function (reason) {
            /// <summary>Resolves this Deferred as having been rejected, passing an optional result value.</summary>
            /// <param name="result" type="Object">Any data to be passed as the result of this Deferred to its rejection handlers.</param>
            if (this.state === 0 /* Pending */) {
                this.state = 2 /* Rejected */;
                this.resultData = reason;

                while (this.rejectedContinuations.length > 0) {
                    this.rejectedContinuations.shift()(this.resultData);
                }

                // Clear the fulfillment continuations.
                this.fulfilledContinuations = null;
            }
        };

        InnerDeferred.prototype.then = function (onFulfilled, onRejected) {
            /// <summary>Registers a continuation for this promise using the specified handlers, both of which are optional, following the Promises/A+ specification.</summary>
            /// <param name="onFulfilled" type="function">A method that is executed if this promise is resolved successfully, accepting the result of the promise (if any) as a parameter.</param>
            /// <param name="onRejected" type="function">A method that is executed if this promise is resolved unsuccessfully (i.e. rejected), accepting the result of the promise (if any) as a parameter.</param>
            /// <returns type="Promise">A Promise with the characteristics defined by the Promises/A+ specification. If neither onFulfilled nor onRejected are valid functions, this method returns the current Promise; otherwise, a new Promise is returned.</returns>
            var _this = this;
            // Define a method to create handlers for a callback.
            var createHandler = function (continuation, callback) {
                // Return a handler that processes the provided data with the callback, calling appropriate methods on the continuation as a result.
                return function (callbackData) {
                    // Queue the execution, capturing the relevant parameters.
                    Promises.Scheduler.scheduleExecution.call(null, function () {
                        // Try to get the result to pass to the continuation from the handler.
                        var callbackResult;
                        try  {
                            // Execute the callback, providing it the given data. This constitutes the callback result (if any).
                            callbackResult = callback(callbackData);
                        } catch (failureHandlerError) {
                            // The failure handler threw an error, so we fail the continuation and pass it the exception as data, terminating execution.
                            continuation.reject(failureHandlerError);
                            return;
                        }

                        // Resolve the continuation with the result.
                        resolvePromise(continuation, callbackResult);
                    });
                };
            };

            // If we aren't passed any valid callbacks, just return the current Promise to save on allocations.
            if (!isFunction(onFulfilled) && !isFunction(onRejected)) {
                // Return the current instance as a Promise, capturing the context of the current "then" method.
                return new Promises.Promise(function (onF, onR) {
                    return _this.then(onF, onR);
                });
            }

            // Per the Promise/A specification:
            //  This function should return a new promise that is fulfilled when the given success or failure callback is finished.
            //  This allows promise operations to be chained together.
            //  The value returned from the callback handler is the fulfillment value for the returned promise. If the callback throws an error, the returned promise will be moved to failed state.
            var continuation = new Deferred();

            // If we have no valid onFulfilled method, use the fulfill method of the Deferred to allow chaining.
            if (!isFunction(onFulfilled)) {
                onFulfilled = continuation.fulfill;
            }

            // If we have no valid onRejected method, use the reject method of the Deferred to allow chaining.
            if (!isFunction(onRejected)) {
                onRejected = continuation.reject;
            }

            // Define the action to take upon successful resolution, wrapping the success handler within the continuation appropriately.
            var successHandler = createHandler(continuation, onFulfilled);

            // Take appropriate action based upon whether this operation has already been resolved.
            if (this.state === 1 /* Fulfilled */) {
                // Invoke the handler, sending in the completion data.
                successHandler(this.resultData);
            } else if (this.state === 0 /* Pending */) {
                // The operation hasn't been resolved, so we queue it up.
                this.fulfilledContinuations.push(successHandler);
            }

            // Define the action to take when the Deferred fails, wrapping the success handler appropriately.
            var failureHandler = createHandler(continuation, onRejected);

            // Take appropriate action based upon whether this operation has already been resolved.
            if (this.state === 2 /* Rejected */) {
                // Invoke the handler, sending in the completion data.
                failureHandler(this.resultData);
            } else if (this.state === 0 /* Pending */) {
                // The operation hasn't been resolved, so we queue it up.
                this.rejectedContinuations.push(failureHandler);
            }

            // Return the promise object for the continuation.
            return continuation.promise();
        };
        return InnerDeferred;
    })();

    //#endregion
    //#region Deferred
    var Deferred = (function () {
        function Deferred() {
            var _this = this;
            // Initialize the Deferred using an InnerDeferred, which defines all the operations and contains all the state.
            // This wrapper simply exposes selective pieces of it.
            var inner = new InnerDeferred();

            this.getState = function () {
                /// <summary>
                /// Gets the state of this Deferred.
                /// </summary>
                /// <returns type="Number">A value from the Deferred.States enumeration.</returns>
                return inner.state;
            };

            // Forward the inner functions, creating closures around them (I'd love to use bind, but it's an ECMA5 standard, plus closures seem to be a lot faster).
            this.promise = function () {
                return new Promises.Promise(_this.then);
            };

            this.reject = function (data) {
                return inner.reject(data);
            };

            this.fulfill = function (result) {
                return inner.fulfill(result);
            };

            this.then = function (onFulfilled, onRejected) {
                return inner.then(onFulfilled, onRejected);
            };
        }
        return Deferred;
    })();
    Promises.Deferred = Deferred;
})(Promises || (Promises = {}));
/*
Promises, Promises...
A light-weight implementation of the Promise/A+ specification (http://promises-aplus.github.io/promises-spec/) and an underlying deferred-execution (i.e. future) provider and useful extensions.
This library is meant to provide core functionality required to leverage Promises / futures within larger libraries via bundling or otherwise inclusion within larger files.
Author:     Mike McMahon
Created:    September 5, 2013
Version:    3.0.2
Updated:    March 16, 2014
Project homepage: http://promises.codeplex.com
*/
/* License (MIT) and copyright information: http://promises.codeplex.com */
/// <reference path="Common interfaces.ts" />
/// <reference path="Scheduler.ts" />
/// <reference path="Deferred.ts" />
var Promises;
(function (Promises) {
    "use strict";

    //#region Utility Methods
    var isFunction = function (itemToCheck) {
        /// <summary>Determines whether an item represents a function.</summary>
        /// <param name="itemToCheck" type="any">An item to examine.</param>
        /// <returns type="Boolean">true if the item is a function; otherwise, false.</returns>
        var f = function () {
        };
        return itemToCheck && ((typeof itemToCheck) === (typeof f));
    };

    //#endregion
    //#region The Promise type
    var Promise = (function () {
        function Promise(thenMethod) {
            /// <summary>
            /// Initializes a new Promise that utilizes the provided method to register continuations.
            /// </summary>
            /// <param name="thenMethod" type="IRegisterPromiseContinuations">A method that fulfills the requirements of the Promise/A+ "then" method.</param>
            // Store the "then" method.
            this.then = thenMethod;
        }
        /// <summary>
        /// An enhanced Promise or future the meets and exceeds the Promise/A+ specification (http://promises-aplus.github.io/promises-spec/), representing an operation that will complete (possibly producing a value) in the future.
        /// </summary>
        /// <field name="always" type="Function(IPromiseContinuation): IPromise">Registers a continuation for this Promise for both fulfillment and rejection. This is a convenience wrapper for the "then" method.</field>
        Promise.prototype.always = function (onFulfilledOrRejected) {
            return this.then(onFulfilledOrRejected, onFulfilledOrRejected);
        };

        //#endregion
        //#region Static Methods
        Promise.fromThenable = function (thenable) {
            /// <summary>
            /// Attempts to consume a "thenable" (i.e. promise-like object), transforming it into a specification-compliant Promise.
            /// This method allows non-compliant promise implementations (e.g. jQuery promises & Deferreds) to be consumed in such a way that their behavior is standardized in a specification-compliant way, ensuring fulfillment and rejection propagation, as well as scheduling compliance.
            /// </summary>
            /// <param name="thenable" type="any">A promise-like entity.</param>
            /// <returns type="Promise">
            /// If 'thenable' does not possess a "then" method, then null.
            /// If attempting to access the "then" method of 'thenable' produces an exception, then a new, rejected Promise is returned whose rejection reason is the exception encountered.
            /// Otherwise, a Promise that represents 'thenable', conveying the fulfillment or rejection values (as produced) by that object.
            /// </returns>
            // Attempt to access the "then" method on the result, if it is present.
            // We perform this action once, safely, since the result may be volatile.
            var thenProperty;
            try  {
                thenProperty = thenable.then;
            } catch (thenError) {
                // We received an error trying to access the "then" method, so we reject the continuation with this error.
                // Note that this does not occur if the "then" method does not exist.
                return Promise.rejectedWith(thenError);
            }

            // If the "then" property is a function, wrap it.
            if (isFunction(thenProperty)) {
                // The return value is promise-like, so, per the specification, we have to try to assume its value.
                // We leverage one of our own Deferred instances as a proxy, wiring it up to the "then" method.
                var proxy = new Promises.Deferred();

                // The handlers passes the arguments object if there is more than 1 value passed to the fulfillment / rejection method by the thenable (this helps with jQuery and other thenables that supply multiple result values); otherwise, it simply passes the single (or undefined) result.
                var createArgumentFilterWrapper = function (wrapped) {
                    return function (r) {
                        (arguments.length > 1) ? wrapped(arguments) : wrapped(r);
                    };
                };

                // Try to invoke the "then" method using the context of the original object.
                // We have to specifically re-apply it in case the original object was mutated, per the specification.
                // We schedule the execution of this method to ensure that we don't get blocked here by the "thenable."
                Promises.Scheduler.scheduleExecution(function () {
                    try  {
                        thenProperty.call(thenable, createArgumentFilterWrapper(proxy.fulfill), createArgumentFilterWrapper(proxy.reject));
                    } catch (thenError) {
                        // We encountered an exception and haven't executed a resolver, reject the promise.
                        proxy.reject(thenError);
                    }
                });

                // Return the proxy.
                return proxy.promise();
            } else {
                // This isn't a "thenable," so we return null.
                return null;
            }
        };

        Promise.fulfilledWith = function (result) {
            /// <summary>
            /// Creates a Promise that has been fulfilled with the (optional) provided result.
            /// This method provides a convenient mechanism for creating a fulfilled Promise when the resulting value is known immediately.
            /// </summary>
            /// <param name="result" type="any">The optional result.</param>
            /// <returns type="Promise">A Promise that is fulfilled with the provided result.</returns>
            // If there is no result provided, use the "fulfilled" static instance to save on allocations.
            // Otherwise, we pass along the provided value.
            if (arguments.length == 0) {
                return Promise.fulfilled;
            } else {
                // Create a Deferred, fulfill it with the result, and return the Promise form.
                var fulfilled = new Promises.Deferred();
                fulfilled.fulfill(result);
                return fulfilled.promise();
            }
        };

        Promise.rejectedWith = function (reason) {
            /// <summary>
            /// Creates a Promise that has been rejected with the (optional) provided reason.
            /// This method provides a convenient mechanism for creating a rejected Promise when the reason for rejection is known immediately.
            /// </summary>
            /// <param name="reason" type="any">The optional reason.</param>
            /// <returns type="Promise">A Promise that is rejected for the specified reason.</returns>
            // If there is no reason provided, use the "rejected" static instance to save on allocations.
            // Otherwise, we pass along the provided value.
            if (arguments.length == 0) {
                return Promise.rejected;
            } else {
                // Create a Deferred, reject it for the reason, and return the Promise form.
                var rejected = new Promises.Deferred();
                rejected.reject(reason);
                return rejected.promise();
            }
        };

        Promise.whenAll = function (promises) {
            /// <summary>
            /// Creates a Promise that is fulfilled when all the specified Promises are fulfilled, or rejected when one of the Promises is rejected.
            /// </summary>
            /// <param name="promises" type="Array" elementType="Promise">A set of promises to represent.</param>
            /// <returns type="Promise">A Promise that is fulfilled when all the specified Promises are fulfilled, or rejected when one of the Promises is rejected.</returns>
            // Take action depending upon the number of Promises passed.
            if (promises.length == 0) {
                // There are no arguments, so we return a completed Promise.
                return Promise.fulfilled;
            } else if (promises.length == 1) {
                // There's only one Promise, so return it.
                return promises[0];
            } else {
                // Create a new Deferred to represent the entire process.
                var whenAll = new Promises.Deferred();

                // Wire into each Promise, counting them as they complete.
                // We count manually to filter out any odd, null entries.
                var pendingPromises = 0;

                for (var i = 0; i < promises.length; i++) {
                    var promise = promises[i];

                    // Increment the total count and store the promise, then wire-up the promise.
                    pendingPromises++;

                    promise.then(function () {
                        // Completed successfully, so decrement the count.
                        pendingPromises--;

                        // If this is the last promise, resolve it, passing the promises.
                        // If a failure occurred already, this will have no effect.
                        if (pendingPromises == 0) {
                            whenAll.fulfill();
                        }
                    }, function (reason) {
                        // A failure occurred, so decrement the count and reject the Deferred, passing the error / data that caused the rejection.
                        // A single failure will cause the whole set to fail.
                        pendingPromises--;
                        whenAll.reject(reason);
                    });
                }

                // Return the promise.
                return whenAll.promise();
            }
        };

        Promise.whenAny = function (promises) {
            /// <summary>
            /// Creates a Promise that is fulfilled when any of the specified Promises are completed.
            /// </summary>
            /// <param name="promises" type="Array" elementType="Promise">A set of promises to represent.</param>
            /// <returns type="Promise">A Promise that is fulfilled when any of the specified Promises are fulfilled or rejected. The returned Promise assumes the state / value of the first completed Promise (i.e. becomes the completed Promise).</returns>
            // Take action depending upon the number of Promises passed.
            if (promises.length == 0) {
                // There are no arguments, so we return a completed Promise.
                return Promise.fulfilled;
            } else if (promises.length == 1) {
                // There's only one Promise, so return it.
                return promises[0];
            } else {
                // Create a new Deferred to represent the entire process.
                var whenAny = new Promises.Deferred();

                for (var i = 0; i < promises.length; i++) {
                    // Fulfill or reject the returned promise using the resurn data of the first to complete.
                    var promise = promises[i];
                    promise.then(function (result) {
                        whenAny.fulfill(result);
                    }, function (reason) {
                        whenAny.reject(reason);
                    });
                }

                // Return the promise.
                return whenAny.promise();
            }
        };
        Promise.never = new Promise(function () {
            // We ignore any parameters since they'll never be executed and we don't need memory consumption to grow unnecessarily.
            // To ensure we return a proper Promise, we return this Promise.never instance.
            return Promise.never;
        });
        return Promise;
    })();
    Promises.Promise = Promise;
})(Promises || (Promises = {}));
/*
Promises, Promises...
A light-weight implementation of the Promise/A+ specification (http://promises-aplus.github.io/promises-spec/) and an underlying deferred-execution (i.e. future) provider and useful extensions.
This library is meant to provide core functionality required to leverage Promises / futures within larger libraries via bundling or otherwise inclusion within larger files.
Author:     Mike McMahon
Created:    September 5, 2013
Version:    3.0.2
Updated:    March 16, 2014
Project homepage: http://promises.codeplex.com
*/
/// <reference path="Promise.ts" />
var Promises;
(function (Promises) {
    "use strict";

    //#region Static Member Implementations
    // These have to be instantiated after the Promise class has defined them and itself.
    Promises.Promise.rejected = (function () {
        /// <summary>Creates a single instance of a Promise that has been rejected (i.e. completed with an error).</summary>
        /// <returns type="Promise">A Promise that has been rejected (i.e. completed with an error).</returns>
        // Resolve a Deferred to represent a failed one, returning it.
        var completed = new Promises.Deferred();
        completed.reject();
        return completed.promise();
    }());

    Promises.Promise.fulfilled = (function () {
        /// <summary>Creates a single instance of a fulfilled (i.e. successfully-resolved) Promise.</summary>
        /// <returns type="Promise">A Promise that has been fulfilled.</returns>
        // Resolve a Deferred to represent a completed one, returning it.
        var completed = new Promises.Deferred();
        completed.fulfill();
        return completed.promise();
    }());
})(Promises || (Promises = {}));
/// <reference path="../../../promises/Promises, Promises/Promises, Promises/Promises/Extensions.ts" />
/// <reference path="DocumentResource.ts" />
/// <reference path="DocumentResourceType.ts" />
var HeadTS;
(function (HeadTS) {
    var ResourceManager = (function () {
        /// <summary>
        /// Provides maangement for resources of a document.
        /// </summary>
        function ResourceManager(doc) {
            /// <summary>
            /// Initializes a new REsourceManager for a document.
            /// </summary>
            // Instantiate the new loader, exposing its loadAsync method on our load method.
            // We close over this instance to hide its existence.
            var managedDoc = new ManagedDocument(doc);
            this.loadAsync = function (resource) {
                return managedDoc.loadAsync(resource);
            };
        }
        return ResourceManager;
    })();
    HeadTS.ResourceManager = ResourceManager;

    var ManagedDocument = (function () {
        function ManagedDocument(doc) {
            this.doc = doc;
            /// <summary>
            /// Initializes a new ManagedDocument.
            /// </summary>
            // Perform the one-time tests on the document, applying the results to appropriate properties.
            this.supportsAsynchronousScripts = ManagedDocument.documentSupportsAsynchronousScripts(doc);
            this.isReady = ManagedDocument.documentIsReady(doc);

            // Initialize the resource collection, which we organize by name using the dictionary-like structure of the Object.
            this.resources = {};
        }
        ManagedDocument.prototype.loadAsync = function (resource) {
            /// <summary>
            /// Loads a new resource into this ManagedDocument.
            /// </summary>
            var _this = this;
            // First, check whether a resource with the same name is already in the resource collection.
            // If it is, return the existing instance Promise; otherwise, create a new one.
            // Our policy is to ignore duplicates.
            var managedResource = this.resources[resource.name], resourceExists = (managedResource !== undefined);

            // If the resource already exists and is defined, this is a re-definition, which we ignore.
            // Consequently, we return the Promise for the existing entry.
            if (resourceExists && managedResource.checkResourceIsPresent()) {
                return managedResource.isLoaded.promise();
            } else {
                // If the resource doesn't exist, create a ManagedDocumentResource to manage it and add it to the collection.
                // Otherwise, the resource exists, but it's a placeholder, so we need to apply this resource as the actual resource for management.
                if (!resourceExists) {
                    this.resources[resource.name] = managedResource = new ManagedDocumentResource(resource);
                } else {
                    managedResource.resource = resource;
                }

                // The resource is now defined (yay!), so we can resolve its dependencies and load it.
                // We return the Promise that represents the resource and its dependencies having been loaded.
                return this.loadDependenciesAsync(managedResource.resource.namedDependencies).then(function () {
                    return _this.loadResourceAsync(managedResource);
                });
            }
        };

        ManagedDocument.prototype.whenLoaded = function (namedResource) {
            var resource = this.resources[namedResource];
            if (resource === undefined) {
                this.resources[namedResource] = resource = new ManagedDocumentResource();
            }

            return resource.isLoaded.promise();
        };

        ManagedDocument.prototype.loadDependenciesAsync = function (namedDependencies) {
            /// <summary>
            /// Loads a set of named dependencies asynchrously.
            /// </summary>
            /// <param name="namedDependencies">A set of named dependencies.</param>
            /// <returns>A Promise that is fulfilled when all the named dependencies have been loaded into the ManagedDocument or rejected if any dependency fails to load.</returns>
            // If there are no dependencies, return a fulfilled Promise to indicate that the dependencies are resolved.
            if (namedDependencies.length === 0) {
                return Promises.Promise.fulfilled;
            }

            // We have dependencies, so start resolving them.
            var dependencies = [];
            for (var i = 0; i < namedDependencies.length; i++) {
                var currentDependencyName = namedDependencies[i], currentResource = this.resources[currentDependencyName];

                // If the dependency is not present, add an entry for it with no associated resource as a placeholder for a later definition.
                // This allows us to attach to a Promise now and fulfill it later. :-)
                if (currentResource === undefined) {
                    this.resources[currentDependencyName] = currentResource = new ManagedDocumentResource();
                }

                // Add the current dependency Promise to the list of dependencies so that we can wait until they're all resolved.
                dependencies.push(currentResource.isLoaded.promise());
            }

            // Return a Promise that represents all the dependencies being loaded.
            return Promises.Promise.whenAll(dependencies);
        };

        ManagedDocument.prototype.loadResourceAsync = function (resource) {
            /// <summary>
            /// Loads a managed resource asnychronously.
            /// </summary>
            /// <param name="resource">The managed resource to load.</param>
            /// <returns>A Promise that is either fulfilled when the managed resource is loaded or rejected when the managed resource fails to load.</returns>
            var _this = this;
            // Create a function to iterate over each source.
            var sourceIndex = 0;
            var loadNextResourceAsync = function () {
                // Load the resource into the document from the specified source.
                // If that works, run the test. If the test passes, fulfill the resource loading Promise.
                // If we can't load that resource or teh test fails, try the next one until one works, or we run out of sources to try.
                // If all sources fail to load, reject the resource loading Promise.
                return _this.loadResourceFromSourceAsync(resource, sourceIndex).then(function () {
                    try  {
                        if (!resource.resource.test()) {
                            return Promises.Promise.rejected;
                        }
                    } catch (testError) {
                        return Promises.Promise.rejected;
                    }
                }).then(function () {
                    return resource.isLoaded.fulfill();
                }, function () {
                    // We failed to load this resource, which is too bad.
                    // Remove the element that failed to load (for cleanliness).
                    resource.element.parentElement.removeChild(resource.element);
                    resource.element = null;

                    // Then try the next one (if one exists); if not, just reject the resource loading.
                    sourceIndex++;
                    if (sourceIndex < resource.resource.sources.length) {
                        loadNextResourceAsync();
                    } else {
                        resource.isLoaded.reject();
                    }
                });
            };

            // Start the loading process.
            loadNextResourceAsync();

            // Return the resource Promise, which represents the loading of the resource itself.
            return resource.isLoaded.promise();
        };

        ManagedDocument.prototype.loadResourceFromSourceAsync = function (resource, sourceIndex) {
            var _this = this;
            // Create a Deferred to represent the operation of attempting to load the resource.
            var result = new Promises.Deferred();

            // Create the element for this resource, assigning it to the managed resource.
            var el = resource.element = this.createElementForResource(resource, sourceIndex);

            // Add event handlers to monitor the element for loading completion / failure.
            // Note that we fallback to window events if the specific event object is not provided in order to support older browsers.
            el.onerror = function (errorEvent) {
                return result.reject(errorEvent || _this.doc.parentWindow.event);
            };
            el.onload = el.onreadystatechange = function (loadEvent) {
                loadEvent = event || _this.doc.parentWindow.event;

                // This is right out of the HeadJs loadAsset method, which has a much more complete list of scenarios.
                // In effect, if this is the event we care about, fulfill the promise.
                if (loadEvent.type === "load" || (/loaded|complete/.test(el.readyState) && (!_this.doc.documentMode || _this.doc.documentMode < 9))) {
                    result.fulfill();
                }
            };

            // Ensure that we properly clear our event handlers.
            result.promise().always(function () {
                el.onerror = el.onload = el.onreadystatechange = null;
            });

            // Append the element to the end of the document head - this ensures that CSS is appended in the proper order for overrides.
            var head = this.doc.head || this.doc.getElementsByTagName("head")[0];
            head.insertBefore(el, head.lastChild);

            // Return the Promise that represents the operation.
            return result.promise();
        };

        ManagedDocument.prototype.createElementForResource = function (resource, sourceIndex) {
            if (resource.resource.type === 0 /* script */) {
                // We're a script element, so we create, configure, and return it.
                var scriptElement = this.doc.createElement("script");
                scriptElement.type = "text/javascript";
                scriptElement.src = resource.resource.sources[sourceIndex];
                scriptElement.async = false;
                scriptElement.defer = false;
                return scriptElement;
            } else {
                // We're a style element, so we create, configure, and return it.
                var styleElement = this.doc.createElement("link");
                styleElement.type = "text/css";
                styleElement.rel = "stylesheet";
                styleElement.href = resource.resource.sources[sourceIndex];
                return styleElement;
            }
        };

        //#region Document Utilities
        ManagedDocument.documentSupportsAsynchronousScripts = function (doc) {
            /// <summary>
            /// Determines whether an HTMLDocument supports asynchronous scripts.
            /// </summary>
            /// <param name="doc" type="HTMLDocument">An HTML document to examine.</param>
            /// <returns type="Boolean">Whether <paramref name="doc" /> supports asynchronous scripts.</returns>
            // We determine that an HTMLDocument supports asynchronous scripts if it passes one of these tests:
            //  1. The script elements support the "async" property. This is the best and clearest test.
            //  2. The browser is Mozilla-based.
            //  3. The browser is Opera.
            return (('async' in doc.createElement('script')) || ('MozAppearance' in doc.documentElement.style) || ('opera' in doc.parentWindow));
        };

        ManagedDocument.documentIsReady = function (doc) {
            // Represent the operation with a Promise using a Deferred internally.
            var ready = new Promises.Deferred(), readyPromise = ready.promise();

            // A small utility wrapper to ensure the document body is present when we get our ready signal (IE can get overzealous - jQuery ticket #5443).
            var ensureReady = function () {
                // If the body isn't present yet, wait for a short time and check again.
                if (!doc.body) {
                    setTimeout(ensureReady, 50);
                } else {
                    ready.fulfill();
                }
            };

            // Attach to the document & window event handlers to ensure we don't miss anything.
            // Try to attach to events using the W3C-compliant methods supported by newer browsers.
            // Otherwise, we have to fallback to older mechanisms, a-la old IE.
            if (doc.addEventListener) {
                // Add some listeners to the document and window events.
                // We monitor both the document and the window (as a fallback).
                doc.addEventListener('DOMContentLoaded', ensureReady, false);
                doc.parentWindow.addEventListener('load', ensureReady, false);

                // Add some cleanup logic.
                readyPromise.always(function () {
                    doc.removeEventListener('DOMContentLoaded', ensureReady, false);
                    doc.parentWindow.removeEventListener('load', ensureReady, false);
                });
            } else {
                // We're old IE, so let's use the older event attachment methods.
                // We once more monitor both the document and window.
                doc.attachEvent('onreadystatechange', ensureReady);
                doc.parentWindow.attachEvent('onload', ensureReady);

                // Add some cleanup logic.
                readyPromise.always(function () {
                    doc.detachEvent('onreadystatechange', ensureReady);
                    doc.parentWindow.detachEvent('onload', ensureReady);
                });
            }

            // We've constructed our Promise and we do one final check in case the DOM completed while we were wiring things up.
            if (doc.readyState === 'complete') {
                ensureReady();
            }

            // Return the Promise.
            return readyPromise;
        };
        return ManagedDocument;
    })();

    var ManagedDocumentResource = (function () {
        /// <field name="resource">The resource that is being managed. This field is assigned via the constructor, if it is provided.</field>
        function ManagedDocumentResource(resource) {
            this.resource = resource;
            /// <summary>
            /// A document resource whose loading is managed.
            /// This class supports the internal operations of the ManagedDocument class.
            /// </summary>
            /// <field name="documentElement">The HTML element that represents this resource. This field is managed by an external class.</field>
            this.element = null;
            /// <field name="loaded">Represents the asynchronous loading of the resource. This is resolved or rejected by a resource manager external to this class.</field>
            this.isLoaded = new Promises.Deferred();
        }
        ManagedDocumentResource.prototype.checkResourceIsPresent = function () {
            /// <summary>
            /// Determines whether this ManagedDocumentResource has been assigned a DocumentResource to manage.
            /// </summary>
            /// <returns>true if this instance has a DocumentResource to manage; otherwise, false.</returns>
            return ((this.resource !== undefined) && (this.resource !== null));
        };
        return ManagedDocumentResource;
    })();
})(HeadTS || (HeadTS = {}));
/// <reference path="DocumentResource.ts" />
/// <reference path="ResourceManager.ts" />
var HeadTS;
(function (HeadTS) {
    var Loader = (function () {
        function Loader(doc) {
            this.doc = doc;
            this.manager = new HeadTS.ResourceManager(doc);
        }
        Loader.prototype.loadAsync = function (resources) {
            // Load each resource using the manager.
            var pendingResources = [];
            for (var i = 0; i < resources.length; i++) {
                pendingResources.push(this.manager.loadAsync(resources[i]));
            }

            // Return a Promise to represent when all the resources have been loaded.
            return Promises.Promise.whenAll(pendingResources);
        };
        return Loader;
    })();
    HeadTS.Loader = Loader;
})(HeadTS || (HeadTS = {}));
//# sourceMappingURL=HeadTS.js.map
